/*
 * Copyright (c) 2024 endless-sky
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "config_command_handler.h"
#include "common_config_manager.h"
#include "utils_log.h"
#include <algorithm>
#include <regex>

namespace El {
namespace Protocol {

ConfigCommandHandler::ConfigCommandHandler()
{
}

void ConfigCommandHandler::RegisterMethodHandlers(
    std::unordered_map<std::string, std::function<nlohmann::json(const std::string &, const nlohmann::json &)>>
        &globalHandlers)
{
    // 注册通用配置获取方法
    globalHandlers["config.get"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandleGetConfig(id, params);
    };

    // 注册通用配置设置方法
    globalHandlers["config.set"] = [this](const std::string &id, const nlohmann::json &params) {
        return HandleSetConfig(id, params);
    };
}

nlohmann::json ConfigCommandHandler::HandleGetConfig(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("处理config.get请求, 参数: {}", params.dump());

    try {
        // 检查name参数（不做兼容）
        if (!params.contains("name") || !params["name"].is_string()) {
            return CreateErrorResponse(id, 400, "缺少必要参数name或参数格式不正确");
        }

        std::string configName = params["name"].get<std::string>();

        EL_DEBUG("请求获取配置名称: {}", configName);

        // 验证和标准化配置名称
        if (!ValidateConfigPath(configName)) {
            return CreateErrorResponse(id, 400, "配置名称格式不正确: " + configName);
        }

        std::string normalizedPath = NormalizeConfigPath(configName);
        EL_DEBUG("标准化配置路径: {}", normalizedPath);

        // 获取配置
        auto& configManager = El::Common::ConfigManager::GetInstance();
        nlohmann::json config = configManager.GetConfig(normalizedPath);

        if (config.is_null()) {
            return CreateErrorResponse(id, 404, "配置路径不存在: " + normalizedPath);
        }

        EL_INFO("成功获取配置: {}", normalizedPath);
        return CreateSuccessResponse(id, config);

    } catch (const std::exception &e) {
        EL_ERROR("获取配置失败: {}", e.what());
        return CreateErrorResponse(id, 500, "获取配置失败: " + std::string(e.what()));
    }
}

nlohmann::json ConfigCommandHandler::HandleSetConfig(const std::string &id, const nlohmann::json &params)
{
    EL_DEBUG("处理config.set请求, 参数: {}", params.dump());

    try {
        // 检查必要参数（不做兼容）
        if (!params.contains("name") || !params["name"].is_string()) {
            return CreateErrorResponse(id, 400, "缺少必要参数name或参数格式不正确");
        }

        if (!params.contains("config")) {
            return CreateErrorResponse(id, 400, "缺少必要参数config");
        }

        std::string configName = params["name"].get<std::string>();
        nlohmann::json config = params["config"];

        EL_DEBUG("请求设置配置名称: {}, 内容: {}", configName, config.dump());

        // 验证和标准化配置名称
        if (!ValidateConfigPath(configName)) {
            return CreateErrorResponse(id, 400, "配置名称格式不正确: " + configName);
        }

        std::string normalizedPath = NormalizeConfigPath(configName);
        EL_DEBUG("标准化配置路径: {}", normalizedPath);

        if (normalizedPath == "/algo_manager") {
            std::string validationMessage;
            if (!ValidateAlgoManagerConfig(config, validationMessage)) {
                if (validationMessage.empty()) {
                    validationMessage = "算法配置校验失败";
                }
                EL_WARN("Algo manager config validation failed: {}", validationMessage);
                return CreateErrorResponse(id, 400, validationMessage);
            }
        }

        // 设置配置
        auto& configManager = El::Common::ConfigManager::GetInstance();
        bool success = configManager.SetConfig(normalizedPath, config);

        if (success) {
            EL_INFO("成功设置配置: {}", normalizedPath);
            return CreateSuccessResponse(id, nlohmann::json{{"status", "success"}, {"message", "配置设置成功"}});
        } else {
            return CreateErrorResponse(id, 500, "设置配置失败");
        }

    } catch (const std::exception &e) {
        EL_ERROR("设置配置失败: {}", e.what());
        return CreateErrorResponse(id, 500, "设置配置失败: " + std::string(e.what()));
    }
}

bool ConfigCommandHandler::ValidateAlgoManagerConfig(const nlohmann::json &config, std::string &errorMessage)
{
    if (!config.is_object()) {
        errorMessage = "算法配置格式错误";
        return false;
    }

    if (!config.contains("algorithms")) {
        return true;
    }

    const auto &algorithms = config["algorithms"];
    if (!algorithms.is_array()) {
        errorMessage = "算法配置格式错误";
        return false;
    }

    size_t enabledCount = 0;
    for (const auto &algorithm : algorithms) {
        if (!algorithm.is_object()) {
            continue;
        }

        if (algorithm.value("enabled", false)) {
            ++enabledCount;
            if (enabledCount > 1) {
                errorMessage = "同一时间仅支持启用一个算法，请先关闭其他算法后重试";
                return false;
            }
        }
    }

    return true;
}

bool ConfigCommandHandler::ValidateConfigPath(const std::string &name)
{
    try {
        // 检查配置名称是否为空
        if (name.empty()) {
            EL_ERROR("配置名称不能为空");
            return false;
        }

        // 检查配置名称是否包含非法字符
        std::regex nameRegex("^[a-zA-Z0-9/_-]+$");
        if (!std::regex_match(name, nameRegex)) {
            EL_ERROR("配置名称包含非法字符: {}", name);
            return false;
        }

        // 检查配置名称长度
        if (name.length() > 256) {
            EL_ERROR("配置名称过长: {}", name);
            return false;
        }

        return true;

    } catch (const std::exception &e) {
        EL_ERROR("验证配置名称时发生异常: {}", e.what());
        return false;
    }
}

std::string ConfigCommandHandler::NormalizeConfigPath(const std::string &name)
{
    std::string normalized = name;

    // 确保配置名称以'/'开头
    if (!normalized.empty() && normalized[0] != '/') {
        normalized = "/" + normalized;
    }

    // 移除重复的'/'
    std::regex duplicateSlashes("/+");
    normalized = std::regex_replace(normalized, duplicateSlashes, "/");

    // 移除末尾的'/'（除非是根路径"/"）
    if (normalized.length() > 1 && normalized.back() == '/') {
        normalized.pop_back();
    }

    return normalized;
}

} // namespace Protocol
} // namespace El
